﻿using System;
using Microsoft.Xna.Framework;
//Szu
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using CharacterLibrary;
using LevelLibrary;

using Global;


using Nuclex.Input;

namespace Pacman_3D
{
    public class Game1 : Microsoft.Xna.Framework.Game
    {
        Creatures creatures;
        GraphicsDeviceManager graphics;
        SpriteBatch spriteBatch;
        Level level;
        Sound sound;
        private Menu menu;
        private IngameMenu pauseMenu;
        HighScores hScores;
        private bool start = false;
        private bool ingameMenu = false;

        /* NUCLEX - GUI / IO / Audio */
        /// <summary>Polls input devices and allows their state to be queried</summary>
        private InputManager inputManager;
        /// <summary>Font used to display text on the screen</summary>
        private SpriteFont displayFont;


        public Game1()
        {
            graphics = new GraphicsDeviceManager(this);            
            graphics.PreferMultiSampling = true;
            graphics.SynchronizeWithVerticalRetrace = true;
            graphics.IsFullScreen = false;
            graphics.PreferredBackBufferWidth = 1024;
            graphics.PreferredBackBufferHeight = 768;
            Content.RootDirectory = "Content";

            this.inputManager = new InputManager(Services, Window.Handle);

            
        }

        public void LoadNextLevel()
        {
            ++Score.CurrentLevel;
            Score.pointsAtLevelStart = Score.pointsSummary;
            UnloadContent();
            LoadContent();
           
        }


        protected override void Initialize()
        {
            Score.inGame = true;
            
            base.Initialize();

        }
 
        protected override void LoadContent()
        {
            
            
            int levelIndex = Score.CurrentLevel - 1;

            level = Content.Load<Level>(GameSettings.readyLevels[levelIndex]);
         
            spriteBatch = new SpriteBatch(GraphicsDevice);
            level.GenerateLevel(this.Content, graphics);
            creatures = new Creatures(this.Content, graphics, level.Columns, level.Rows, level.Values);

            // Load the font we'll be using for the text display
            displayFont = Content.Load<SpriteFont>("nuclex font/DisplayFont");
            // load Sound object and play the intro
            sound = new Sound(this.Content);
            Sound.intro.Play();
            menu = new Menu(Content);
            pauseMenu = new IngameMenu();
            hScores = new HighScores();
        }

        protected override void UnloadContent()
        {
            Content.Unload();
            spriteBatch.Dispose();
            sound.Dispose();
            spriteBatch = null;
            creatures = null;
            level = null;
            displayFont = null;
            
        }
        
        public TimeSpan inGameTime;

        protected override void Update(GameTime gameTime)
        {
            KeyboardState keys = Keyboard.GetState();

            //Game Loop:
              // menu
            if( !start && (menu.Update( gameTime )) )
            {
              start = true;
            }
          
            if(!ingameMenu)
            {

              //TODO: reakcje na różne wydarzenia
              if( !creatures.Update( gameTime, keys ) )
              {
                if( (Global.Score.elapsedLives > 0) &&
                    (Global.Score.CurrentLevel < Global.GameSettings.numberOfLevels)
                  )
                {
                  //TODO:
                  //FIXME:
                  //po zebraniu wszystkich złociszy i zostawieniu jakiegokolwiek 
                  //białego cukierka, nie przełazimy od razu na następny level,
                  //dopóki go też nie zeżremy.
                  LoadNextLevel();
                }
                else
                {
                  // zapisanie do pliku uzyskanego wyniku
                  HighScores.Data d = new HighScores.Data();
                  d.name = "zzz";
                  d.lvl = Score.CurrentLevel;
                  d.pts = Score.pointsSummary;
                  hScores.scoresList.Add( d );
                  hScores.writeToFile();
                  Score.inGame = false;
                  this.Exit();
                }
              }
            }

            if( ingameMenu )
            {
              if( pauseMenu.Update( gameTime ) )
              {
                ingameMenu = false;
              }

              if( pauseMenu.mainMenuReturn )
              {
                Score.Reset();
                ingameMenu = false;
                start = false;
                menu.Stan = Menu.Status.FirstMenuPos;
                pauseMenu.mainMenuReturn = false;
                UnloadContent();
                LoadContent();
                inGameTime = TimeSpan.Zero;
              }

            }


            
            if (KeyboardExt.keyPressedOnce(Controls.exit))
            {
              if( !start )
              {
                menu.BGTex = Menu.Background.Default;
                menu.menuCounterFreeze = false;

              }
              else
              {
                if( !ingameMenu )
                  ingameMenu = true;
                else
                  ingameMenu = false;

                pauseMenu.Stan = IngameMenu.Status.FirstMenuPos;

              }


            }

            if( menu.killSwitch || pauseMenu.killSwitch )
            {
              this.Exit();

            }
            

            if (KeyboardExt.keyPressedOnce(Controls.skipLevel))
            {
                LoadNextLevel();
            }
            
            base.Update(gameTime);

            
        }

        private void DrawGUI( GameTime gameTime )
        {

          inGameTime += gameTime.ElapsedGameTime;

          spriteBatch.Begin();
          {
            int secondsInGame = inGameTime.Seconds;
            
            spriteBatch.DrawString
                (
                    this.displayFont, "Game time: " + secondsInGame + " s", new Vector2( 50, 50 ),
                    Color.LightGreen
                );
            if( Score.indestructibleTimeLeft != TimeSpan.Zero )
            // wyświetl pozostały czas tylko jeśli pacman jest niezniszczalny
            {
              spriteBatch.DrawString
                  (
                      this.displayFont,
                      "Indestructible time left: " + Score.indestructibleTimeLeft.Seconds + " s",
                      new Vector2( 250, 50 ), Color.LightGreen
                  );
            }
            spriteBatch.DrawString
                (
                    this.displayFont, "Level: " + Score.CurrentLevel, new Vector2( 50, 625 ), Color.LightGreen
                );
            spriteBatch.DrawString
                (
                    this.displayFont, "Points (current level): " + Score.points, new Vector2( 50, 650 ),
                    Color.LightGreen
                );
            spriteBatch.DrawString
                (
                    this.displayFont, "Points (all levels): " + Score.pointsSummary, new Vector2( 50, 675 ),
                    Color.LightGreen
                );
            spriteBatch.DrawString
                (
                    this.displayFont, "Lives: " + Score.elapsedLives, new Vector2( 50, 700 ), Color.LightGreen
                );
          }
          spriteBatch.End();
        }

        private void DrawHighScoreList()
        {
          spriteBatch.Begin();
          spriteBatch.Draw( menu.GetScreen(), menu.pozycja, Color.White );
          if( menu.BGTex == Menu.Background.Scores )
          {
            for( int i = 0; i < hScores.scoresList.Count; i++ )
            {
              spriteBatch.DrawString
              (
                  this.displayFont, hScores.scoresList[i].name, new Vector2( 200, 400 + i * 20 ),
                  Color.WhiteSmoke
              );
              spriteBatch.DrawString
              (
                  this.displayFont, " " + hScores.scoresList[i].lvl + " lvl", new Vector2( 200 + 200, 400 + i * 20 ),
                  Color.WhiteSmoke
              );
              spriteBatch.DrawString
              (
                  this.displayFont, " " + hScores.scoresList[i].pts + " pts", new Vector2( 200 + 400, 400 + i * 20 ),
                  Color.WhiteSmoke
              );
            }
          }
          spriteBatch.End(); 
        }

        protected void DrawIngameMenu( GameTime gameTime )
        {
          const int size = 3;
          string[] stringList = { "Continue", "Back to Main Menu", "Exit" };
          int[] posList = { 200, 250, 300 };

          spriteBatch.Begin();
          {

            spriteBatch.DrawString( displayFont, "PAUSE MENU", new Vector2( 100, 100 ), Color.Azure, 0.0f, new Vector2( 3, 0 ), 2.0f, SpriteEffects.None, 0 );

            for( int i = 0; i < size; ++i )
            {
              if( i + 1 == (int)pauseMenu.Stan )
              {
                spriteBatch.DrawString( displayFont, stringList[i], new Vector2( 100, posList[i] ), Color.Red, 0.0f, new Vector2( 0, 0 ), 1.5f, SpriteEffects.None, 0 );
              }
              else
              {
                spriteBatch.DrawString( displayFont, stringList[i], new Vector2( 100, posList[i] ), Color.White, 0.0f, new Vector2( 0, 0 ), 1.5f, SpriteEffects.None, 0 );

              }

            }

            
          }
          spriteBatch.End();
        }

        protected override void Draw(GameTime gameTime)
        {
            GraphicsDevice.Clear(Color.Black);
            
            
            
            // menu
            if (!start)
            {
              DrawHighScoreList();
            }
            else
            {
              if( ingameMenu )
                DrawIngameMenu( gameTime );
              else
              {
                DrawGUI( gameTime );
                level.Draw();
                creatures.Draw();
              }
            }

            
            

            base.Draw(gameTime);
        }
    }
}
